package com.example.javapoet.demo.basic;

import com.squareup.javapoet.*;

import javax.lang.model.element.Modifier;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

/**
 * JavaPoet基础示例 - 生成Java接口
 */
public class BasicInterfaceGeneration {

    public static void main(String[] args) {
        // 生成一个简单的接口
        generateSimpleInterface();
        
        // 生成一个带泛型的接口
        generateGenericInterface();
        
        // 生成一个带默认方法的接口（Java 8+）
        generateInterfaceWithDefaultMethods();
    }

    /**
     * 生成一个简单的接口
     */
    public static void generateSimpleInterface() {
        // 创建方法
        MethodSpec findByIdMethod = MethodSpec.methodBuilder("findById")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(ClassName.get("com.example.model", "User"))
                .addParameter(long.class, "id")
                .build();
        
        MethodSpec findAllMethod = MethodSpec.methodBuilder("findAll")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(ParameterizedTypeName.get(
                        ClassName.get(List.class),
                        ClassName.get("com.example.model", "User")))
                .build();
        
        MethodSpec saveMethod = MethodSpec.methodBuilder("save")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(ClassName.get("com.example.model", "User"))
                .addParameter(ClassName.get("com.example.model", "User"), "user")
                .build();
        
        MethodSpec deleteMethod = MethodSpec.methodBuilder("delete")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(boolean.class)
                .addParameter(long.class, "id")
                .build();
        
        // 创建接口
        TypeSpec userRepositoryInterface = TypeSpec.interfaceBuilder("UserRepository")
                .addModifiers(Modifier.PUBLIC)
                .addMethod(findByIdMethod)
                .addMethod(findAllMethod)
                .addMethod(saveMethod)
                .addMethod(deleteMethod)
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.repository", userRepositoryInterface)
                .build();

        try {
            // 输出到控制台
            System.out.println("生成UserRepository接口:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成UserRepository.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成一个带泛型的接口
     */
    public static void generateGenericInterface() {
        // 定义泛型类型变量
        TypeVariableName typeT = TypeVariableName.get("T");
        TypeVariableName typeID = TypeVariableName.get("ID");
        
        // 创建方法
        MethodSpec findByIdMethod = MethodSpec.methodBuilder("findById")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(typeT)
                .addParameter(typeID, "id")
                .build();
        
        MethodSpec findAllMethod = MethodSpec.methodBuilder("findAll")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(ParameterizedTypeName.get(
                        ClassName.get(List.class),
                        typeT))
                .build();
        
        MethodSpec saveMethod = MethodSpec.methodBuilder("save")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(typeT)
                .addParameter(typeT, "entity")
                .build();
        
        MethodSpec deleteMethod = MethodSpec.methodBuilder("delete")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(boolean.class)
                .addParameter(typeID, "id")
                .build();
        
        // 创建接口
        TypeSpec genericRepositoryInterface = TypeSpec.interfaceBuilder("GenericRepository")
                .addModifiers(Modifier.PUBLIC)
                .addTypeVariable(typeT)
                .addTypeVariable(typeID)
                .addMethod(findByIdMethod)
                .addMethod(findAllMethod)
                .addMethod(saveMethod)
                .addMethod(deleteMethod)
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.repository", genericRepositoryInterface)
                .build();

        try {
            // 输出到控制台
            System.out.println("\n生成GenericRepository接口:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成GenericRepository.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成一个带默认方法的接口（Java 8+）
     */
    public static void generateInterfaceWithDefaultMethods() {
        // 创建常量字段
        FieldSpec versionField = FieldSpec.builder(String.class, "API_VERSION")
                .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
                .initializer("$S", "v1.0")
                .build();
        
        // 创建抽象方法
        MethodSpec processMethod = MethodSpec.methodBuilder("process")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(String.class)
                .addParameter(String.class, "data")
                .build();
        
        MethodSpec validateMethod = MethodSpec.methodBuilder("validate")
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                .returns(boolean.class)
                .addParameter(String.class, "data")
                .build();
        
        // 创建默认方法
        MethodSpec processWithLoggingMethod = MethodSpec.methodBuilder("processWithLogging")
                .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
                .returns(String.class)
                .addParameter(String.class, "data")
                .addStatement("System.out.println($S + data)", "Processing: ")
                .beginControlFlow("if (!validate(data))")
                .addStatement("throw new $T($S)", IllegalArgumentException.class, "Invalid data")
                .endControlFlow()
                .addStatement("String result = process(data)")
                .addStatement("System.out.println($S + result)", "Result: ")
                .addStatement("return result")
                .build();
        
        MethodSpec getVersionMethod = MethodSpec.methodBuilder("getVersion")
                .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT, Modifier.STATIC)
                .returns(String.class)
                .addStatement("return API_VERSION")
                .build();
        
        // 创建接口
        TypeSpec dataProcessorInterface = TypeSpec.interfaceBuilder("DataProcessor")
                .addModifiers(Modifier.PUBLIC)
                .addField(versionField)
                .addMethod(processMethod)
                .addMethod(validateMethod)
                .addMethod(processWithLoggingMethod)
                .addMethod(getVersionMethod)
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.service", dataProcessorInterface)
                .build();

        try {
            // 输出到控制台
            System.out.println("\n生成DataProcessor接口:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成DataProcessor.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}